package cn.ulyer.core.config;


import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.ulyer.common.annotation.Log;
import cn.ulyer.common.jpa.entity.ActionLog;
import cn.ulyer.common.security.LoginUser;
import cn.ulyer.common.utils.Result;
import cn.ulyer.common.utils.SecurityUtil;
import cn.ulyer.common.utils.WebUtils;
import cn.ulyer.core.modules.system.service.TActionLogService;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Slf4j
public class LogAspect {


    @Pointcut("@annotation(cn.ulyer.common.annotation.Log)")
    public void pointCut(){}

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private TActionLogService tActionLogService;

    @Around(value = "pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = WebUtils.getRequest();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        ActionLog.ActionLogBuilder builder = ActionLog.builder();
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Log targetAnnotation = targetMethod.getAnnotation(Log.class);
        LoginUser loginUser = SecurityUtil.getUser();
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));

        builder.javaMethod(targetClass.getName() + "." + targetMethod.getName())
                .action(targetAnnotation.action())
                .module(targetAnnotation.module())
                .actionUserId(loginUser == null ? null : loginUser.getId())
                .device(userAgent.getBrowser().getName())
                .requestIp(ServletUtil.getClientIP(request))
                .requestUrl(request.getRequestURI().replace(request.getContextPath(), ""))
                .sysName(userAgent.getOs().getName())
                .httpMethod(request.getMethod());
        Object result ;

        Exception ex = null;
        try{
           result = joinPoint.proceed();
        }catch (Exception e){
            result = ExceptionUtil.stacktraceToString(e,2000);
            ex = e;
        }
        ActionLog actionLog = builder.build();
        if(result instanceof Result){
            try{
                actionLog.setResponseBody(JSON.toJSONString(result));
            }catch (Exception e){
                log.error("logAspect object result serialize error method:{}  stack:{}",actionLog.getJavaMethod(),e);
            }
        }
        //不读取body
        actionLog.setRequestParams(objectMapper.writeValueAsString(ServletUtil.getParamMap(request)));
        tActionLogService.save(actionLog);
        if(ex!=null){
            throw ex;
        }
        return result;
    }



}
